/*
  Copyright (C) 2006 by Lukas Loehrer

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

  Author: Lukas Loehrer <loehrerl [at] gmx [dot] net>
*/


// Log levels
const NONE = 0;
const ALL = 255;
const ERROR = 1;
const WARN = 2;
const DEBUG = 4;
const INFO = 8
	const PROFILE = 16;

function Logger(filePath) {
	try {
		var logFile = Components
		.classes["@mozilla.org/file/local;1"]
		.createInstance(Components.interfaces.nsILocalFile);
		logFile.initWithPath(filePath);

		this.outstream = Components
		.classes["@mozilla.org/network/file-output-stream;1"]
		.createInstance(Components.interfaces.nsIFileOutputStream);
		this.outstream.QueryInterface(Components.interfaces.nsISeekableStream);
		this.outstream.init(logFile, 0x02 | 0x08 | 0x10, 0644, 0); // write, create, truncate
	} catch (e) {
		// Well, what can we do ...
		throw e;
	}
	this.logLevel = ALL;
}

function close() {
  this.outstream.close();
}

function log(message, level) {
	if (this.logLevel & level != 0) {
		this._write(this.formatDate(new Date()) + " " + message + "\n");
	}
}

function info(message) {
	this.log("INFO: " + message, INFO);
}

function warn(message) {
	this.log("WARNING: " + message, WARN);
}

function error(message, exception) {
	this.log("ERROR: " + message +
			 (exception ?"\n" + _formatStackTrace1(exception) : ""),
			 ERROR);
}

function debug(message) {
	this.log("DEBUG: " + message, DEBUG);
}

function profile(startTime, message) {
	this.log("PROFILE: " + (Date.now() - startTime) + " ms: " + message, PROFILE);
}

// private functions
function _write(data) {
	// We have a race condition here, but we do not care...
	this.outstream.seek(2, 0);
	// Go to the end of the log file first (in case it is used by other people)
  this.outstream.write(data, data.length);
  this.outstream.flush();
}

// Date formatting
function formatDate(date) {
	var zeroPad = function (n, width) {
		var s = n.toString();
		for (var i = s.length; i < width; i++)  {
			s = "0" + s;
		}
		return s;
	}

	return zeroPad(1900 + date.getYear(), 4) + "-" +
		zeroPad(date.getMonth() + 1, 2) + "-" +
		zeroPad(date.getDate(), 2) + " " +
		zeroPad(date.getHours(), 2) + ":" +
		zeroPad(date.getMinutes(), 2) + ":" +
		zeroPad(date.getSeconds(), 2) + "." +
		zeroPad(date.getTime() % 1000, 3);
}

function _formatStackTrace1(exception) {
    var trace = '';                
    if(exception && exception.stack) {
        var calls = exception.stack.split('\n');
        for (var i = 0, call; i < calls.length; i++) {
			call = calls[i];
            if(call.length > 0) {
                call = call.replace(/\\n/g, '\n');
                            
                if(call.length > 200)
                    call = call.substr(0, 200) + '[...]\n';
                            
                trace += call.replace(/^/mg, '\t') + '\n';
            }
        }
    }
    return trace;
}

function debugImport(name, importAction) {
	var imported = null;
	try {
		this.info("About to import " + name);
		imported = importAction();
		this.info(name + " imported successfully.");
	} catch (e) {
		this.error("Importing " + name + " failed." + e, e);
	}
	return imported;
}

// Setup filelogger prototype
Logger.prototype = {
  _write: _write,
  close: close,
  log: log,
  info: info,
  warn: warn,
  error: error,
  debug: debug ,
  profile: profile,
  formatDate:formatDate,
  debugImport: debugImport
};

// Set up a logger with the default log file
// Use preferences to change its location
var defaultLogFile = Components
	.classes["@mozilla.org/preferences-service;1"]
	.getService(Components.interfaces.nsIPrefBranch)
	.getCharPref('extensions.firemacs.filelogger.defaultLogFile');
defaultLogFile = defaultLogFile || "/dev/null";
var logger = new Logger(defaultLogFile);
//logger.debug("Hello default logger");
